#include "Revision.h"

MercurialRevision::MercurialRevision(std::string f) : Revision (f)
{
    error = "E";
    revNotation = "-1";
    // Note: -1 is the default value that Mercurial specifies when no
    // commits have been made.
}

std::string MercurialRevision::get()
{
    #if defined(_DEBUG)
    // Run Mercurial command to get revision number (changeset) of current working directory
    revNotation = exec("hg id -n");
    // Only save if no error occurred when executing the command
    if (revNotation.compare(error) != 0)
    {
        clean(); // Clean up project
        save();
    }
    #endif

    read();

    return revNotation;
}

// Original code courtesy of: http://stackoverflow.com/questions/478898/how-to-execute-a-command-and-get-output-of-command-within-c
// May need to replace popen and pclose with _popen and _pclose for Windows.
std::string MercurialRevision::exec(std::string cmd)
{
    FILE* pipe = popen(cmd.c_str(), "r");
    if (!pipe)
        return error;

    char buffer[128];
    std::string result = "";
    while (!feof(pipe))
    {
        if (fgets(buffer, 128, pipe) != NULL)
            result += buffer;
    }
    pclose(pipe);

    return result;
}
void MercurialRevision::clean()
{
    // Mercurial adds a "+" symbol if the current working directory has
    // deviated from the commit. Additionally, exec() may leave a new
    // line at the end. We look for these problems and remove then.
    std::string tmp = revNotation.substr(revNotation.size()-1,1);
    if (tmp.compare("\n") == 0)
    {
        revNotation = revNotation.substr(0,revNotation.size()-1);
    }
    tmp = revNotation.substr(revNotation.size()-1,1);
    if (tmp.compare("+") == 0)
    {
        revNotation = revNotation.substr(0,revNotation.size()-1);
    }
}
bool MercurialRevision::save()
{
    std::ofstream file(filename.c_str());
    file << revNotation << std::endl;
    file.close();

    return true;
}
bool MercurialRevision::read()
{
    std::ifstream file(filename.c_str());

    if (file != 0)
    {
        file >> revNotation;
    }
    else
    {
        return false;
    }

    file.close();

    return true;
}
